package br.eng.eliseu.gwt.gestaoWeb.client;

import br.eng.eliseu.gwt.gestaoWeb.client.event.LoginEvent;
import br.eng.eliseu.gwt.gestaoWeb.client.event.LoginEventHandler;
import br.eng.eliseu.gwt.gestaoWeb.client.event.LogoutEvent;
import br.eng.eliseu.gwt.gestaoWeb.client.event.LogoutEventHandler;
import br.eng.eliseu.gwt.gestaoWeb.client.event.MainEvent;
import br.eng.eliseu.gwt.gestaoWeb.client.event.MainEventHandler;
import br.eng.eliseu.gwt.gestaoWeb.client.event.PlaceEvent;
import br.eng.eliseu.gwt.gestaoWeb.client.event.PlaceEventHandler;
import br.eng.eliseu.gwt.gestaoWeb.client.handle.DownloadHandler;
import br.eng.eliseu.gwt.gestaoWeb.client.mvp.PortalResource;
import br.eng.eliseu.gwt.gestaoWeb.client.mvp.PresenterMenuEnum;
import br.eng.eliseu.gwt.gestaoWeb.client.mvp.presenter.Presenter;
import br.eng.eliseu.gwt.gestaoWeb.client.mvp.presenter.PresenterService;
import br.eng.eliseu.gwt.gestaoWeb.client.mvp.presenter.PresenterServiceImpl;
import br.eng.eliseu.gwt.gestaoWeb.client.mvp.view.BaseDisplay;
import br.eng.eliseu.gwt.gestaoWeb.client.ui.MainPresenter;
import br.eng.eliseu.gwt.gestaoWeb.client.ui.MainView;
import br.eng.eliseu.gwt.gestaoWeb.client.util.StringUtil;

import com.google.gwt.core.client.GWT;
import com.google.gwt.user.client.ui.HasWidgets;
import com.google.inject.Inject;

public class AppController implements Presenter {

	private final PresenterService presenterViewService;
	private final PortalResource recursos;

	private MainPresenter mainPresenter;
	private HasWidgets container;
	
	@Inject
	public AppController( MainPresenter mainPresenter,  PortalResource recurso) {
		presenterViewService = GWT.create(PresenterServiceImpl.class);

		this.mainPresenter = mainPresenter;
		this.recursos = recurso;
		
		bind();
	}

	public void bind() {
		// --- Implementaar os eventos Globais Aqui
		
		// Sempre que um evento EventBus.fireEvent( new PlaceEvent.. ) for invocado este evento sera executado
		getRecursos().getEventBus().addHandler(PlaceEvent.TYPE, new PlaceEventHandler() {

			public void onChangePlace(PlaceEvent event) {
				PresenterMenuEnum code = event.getTela();
				showPresenterCode(code);
			}
		});	
		
		getRecursos().getEventBus().addHandler(MainEvent.TYPE, new MainEventHandler() {

			public void onMainPlace(MainEvent event) {
				showPresenterMain();
			}
		});	
		

		// --- sempre que um evento LogOUT for acionado 
		getRecursos().getEventBus().addHandler(LogoutEvent.TYPE, new LogoutEventHandler() {
			public void onLogout(LogoutEvent logoutEvent) {
				// --- Seto null nas variaveis de recursos do sistema
				getRecursos().setUsrAutentidado(null);

				reconstroiTelaPrincipal();
				
			}
		});	

		// --- sempre que um evento LogIN for acionado 
		getRecursos().getEventBus().addHandler(LoginEvent.TYPE, new LoginEventHandler() {

			public void onProcessa(LoginEvent event) {
				// --- Seto o usuario nas variaveis de recursos do sistema
				getRecursos().setUsrAutentidado(event.getUsuarioVO());
				
				reconstroiTelaPrincipal();

			}
		});	

		
		
	}

	// --- Comessa aqui
	public void init(HasWidgets container) {
		this.container = container;
		
		// --- Inicia o Presenter principal "main"
		if ( this.mainPresenter==null){
			// --- So entra aqui se o Injetor nao consegui instanciar o MainPresenter
			this.mainPresenter = new MainPresenter(new MainView(), getRecursos());
		}
		
		if (this.container!=null){
			this.container.clear();
			mainPresenter.go();
			this.container.add( mainPresenter.getDisplay().asWidget() );

		}
		
		getRecursos().getPlaceManager().currentPlace();
		
		
	}
	
	
	private void showPresenterCode(final PresenterMenuEnum s) {
		
		presenterViewService.downloadPresenter(s, new DownloadHandler() {
			
			public void finished(final Presenter presenter) {
				mainPresenter.getDisplay().showState(presenter, s);
			}

			public void failure(Throwable error) {
				System.out.println("Download error: "+error.getMessage()+" ("+s.getNome()+")");
				error.printStackTrace();
			}
		});
	}

	private void showPresenterMain() {
		
		// Criei este metodo assim por se tratar de chamadas asincronas e o que estava acontecendo 
		// é que a primeira chamada nao tinha erminado entes da proxima comessar, assim 
		// a a ultima tela ficava repetida para todas
		
		presenterViewService.downloadPresenter(PresenterMenuEnum.CABECALHO, new DownloadHandler() {
			
			public void finished(final Presenter presenter) {
				mainPresenter.getDisplay().showState(presenter, PresenterMenuEnum.CABECALHO);
				
				presenterViewService.downloadPresenter(PresenterMenuEnum.MENUSITE, new DownloadHandler() {
					
					public void finished(final Presenter presenter) {
						mainPresenter.getDisplay().showState(presenter, PresenterMenuEnum.MENUSITE);
						
						presenterViewService.downloadPresenter(PresenterMenuEnum.MENUSISTEMA, new DownloadHandler() {
							
							public void finished(final Presenter presenter) {
								mainPresenter.getDisplay().showState(presenter, PresenterMenuEnum.MENUSISTEMA);
								
								presenterViewService.downloadPresenter(PresenterMenuEnum.RODAPE, new DownloadHandler() {
									
									public void finished(final Presenter presenter) {
										mainPresenter.getDisplay().showState(presenter, PresenterMenuEnum.RODAPE);
										
										presenterViewService.downloadPresenter(PresenterMenuEnum.HOME, new DownloadHandler() {
											
											public void finished(final Presenter presenter) {
												mainPresenter.getDisplay().showState(presenter, PresenterMenuEnum.HOME);
												
											}

											public void failure(Throwable error) {
												System.out.println("Download error: "+error.getMessage()+" ("+PresenterMenuEnum.HOME.getNome()+")");
												error.printStackTrace();
											}
										});
									}

									public void failure(Throwable error) {
										System.out.println("Download error: "+error.getMessage()+" ("+PresenterMenuEnum.RODAPE.getNome()+")");
										error.printStackTrace();
									}
								});
							}

							public void failure(Throwable error) {
								System.out.println("Download error: "+error.getMessage()+" ("+PresenterMenuEnum.MENUSISTEMA.getNome()+")");
								error.printStackTrace();
							}
						});
					}

					public void failure(Throwable error) {
						System.out.println("Download error: "+error.getMessage()+" ("+PresenterMenuEnum.MENUSITE.getNome()+")");
						error.printStackTrace();
					}
				});
			}

			public void failure(Throwable error) {
				System.out.println("Download error: "+error.getMessage()+" ("+PresenterMenuEnum.CABECALHO.getNome()+")");
				error.printStackTrace();
			}
		});
	}

	
	
	private void reconstroiTelaPrincipal() {
		/* Reconstruo o Menu e chamo o HOME ou uma outra tela que ja esta na url
		 */
		PlaceEvent placeEvent; 
		placeEvent = new PlaceEvent();
		placeEvent.setTela(PresenterMenuEnum.MENUSITE);
		getRecursos().getEventBus().fireEvent(placeEvent);
		
		placeEvent = new PlaceEvent();
		placeEvent.setTela(PresenterMenuEnum.MENUSISTEMA);
		getRecursos().getEventBus().fireEvent(placeEvent);
		
		/* Vejo no token do History se tem alguma tela que ja foi chamada.
		 * Se nao tiver nada com a identificacao eu abro o Home 
		 */
		String tokenHistory = getRecursos().getPlaceManager().getPresenterName();
		if (tokenHistory!=null && StringUtil.right(tokenHistory, 1).equals("_")){
			/* Chamo a tela que foi chamada, provavelmente direto da url, e que nescessitou de login
			 */
			tokenHistory = tokenHistory.substring(0, tokenHistory.length()-1);
			getRecursos().getPlaceManager().newPlace(tokenHistory);
		} else {
			/*  Se nao tem a marcacao que indica que este login foi acionado por 
			 *  uma tela que precisa de autenticacao, eu abro o HOME 
			 */
			if (getRecursos().getUsrAutentidado()==null){
				getRecursos().getPlaceManager().newPlace(PresenterMenuEnum.HOME);
			} else {
				getRecursos().getPlaceManager().newPlace(PresenterMenuEnum.HOMESISTEMA);
			}
		}
	}
	
	
	
	public void go() {
		// TODO Auto-generated method stub
	}

	public BaseDisplay getDisplay() {
		return null;
	}
	public PortalResource getRecursos() {
		return recursos;
	}


}
